import java.util.Collections;
public class Polygon {

  ArrayList<PVector> points;
  EdgesTable edges;

  public Polygon(ArrayList<PVector> points) {
    this.points = points;
  }
  public Polygon() {
    this.points = new ArrayList<PVector>();
  }

  /* This will add an edge formed by the provided point
   and the last point provided throug this method.
   */
  public void addPoint(PVector nextPoint) {
    this.points.add(nextPoint);
  }

  public void draw(color c, boolean complete) {
    color oldC = get(0, 0); 
    stroke(c);
    if (points.size()>1) {
      int x1, y1;
      int x0 = (int)this.points.get(0).x;
      int y0 = (int)this.points.get(0).y;
      for (int i=1; i<points.size()+((complete)?1:0); i++) {
        x1 = (int)this.points.get(i%points.size()).x;
        y1 = (int)this.points.get(i%points.size()).y;
        line(x0, y0, x1, y1);
        x0 = x1;
        y0 = y1;
      }
    }
    stroke(oldC);
  }

  public void rotate(float angle) {
    this.rotate(angle, new PVector(0, 0));
  }

  public void rotate(float angle, PVector referencePoint) {
    this.translate((int)(-1*referencePoint.x), (int)(-1*referencePoint.y));
    for (int i=0; i<points.size(); i++) {
      float x = points.get(i).x;
      float y = points.get(i).y;

      PVector newP = new PVector(x*cos(angle)-y*sin(angle), x*sin(angle)+y*cos(angle));

      points.set(i, newP);
    }
    this.translate((int)(referencePoint.x), (int)(referencePoint.y));
  }

  public void translate(int x, int y) {
    for (int i=0; i<points.size(); i++) {
      PVector newP = new PVector(points.get(i).x + x, points.get(i).y + y);
      points.set(i, newP);
    }
  }

  public void scale(float percent) {
    for (int i=0; i<points.size(); i++) {
      println(points.get(i));
      PVector newP = new PVector(points.get(i).x * percent, points.get(i).y * percent);
      points.set(i, newP);
    }
  }

  public void fill(color c) {
    color oldC = get(0, 0); 
    EdgesTable table = new EdgesTable(points);
    stroke(c);
    int y = table.getMinY();
    ArrayList<Edge> activeTable = table.getActiveEdgeTable(y);

    while (activeTable.size () > 0) {
      //draw
      for (int i=0; i<activeTable.size()-1; i+=2) {
        Edge e1 = activeTable.get(i);
        Edge e2 = activeTable.get(i+1);
        line(e1.minX,y,e2.minX,y);
      }
      y++;
      //update active table
      int size = activeTable.size();
      for (int i=0; i<size; i++) {
        Edge e = (Edge)activeTable.get(i);
        if (e.maxY < y) {
          activeTable.remove(e);
          size--;
          i--;
        }
      }
      //update list
      ArrayList<Edge> next = table.getActiveEdgeTable(y);
      for (int i=0; i<activeTable.size(); i++) {
        Edge e = (Edge)activeTable.get(i);
        e.update();
      }
      activeTable.addAll(next);
      Collections.sort(activeTable);
    }

    stroke(oldC);
  }
}

